using System;
using System.IO;
using System.IO.Compression;
using System.Collections.Generic;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.Xml.Serialization;

namespace MonsterNet
{
	public abstract class MNSerialise
	{

		#region helpers
		
		/*
		public static void SerialiseIList<T>(SerializationInfo info, string name, IList<T> array) {{
			int i = 0;
			foreach (T item in array) {
				info.AddValue(string.Format(@"{0}:{1}",name,i),item);
				i++;
			}
		}
		*/

		#endregion
		
		#region Load/Save Methods
			
		/// <summary>
		/// Load object from file 
		/// </summary>
		/// <param name="filename">
		/// A <see cref="System.String"/>
		/// </param>
		/// <returns>
		/// A <see cref="T"/>
		/// </returns>
		
		public static T LoadFromFile<T>(string filename)where T : class, new() {
			return LoadFromFile<T>(filename, false);
		}
		
		public static T LoadFromFile<T>(string filename, bool compress)where T : class, new() {
			T loadedObj;
						
			if( File.Exists(filename) )
			{
				FileStream fs = null;
				BinaryFormatter bf = new BinaryFormatter();
				GZipStream decompressor = null;
				
				try {	
					fs = File.Open(filename, FileMode.Open, FileAccess.Read);
				} catch(Exception ex) {
					//TODO: file load error
					Console.WriteLine(ex.ToString());
					return new T();
				}
				
				try {
					if(compress) {
						decompressor = new GZipStream(fs, CompressionMode.Decompress);
						loadedObj = (T)bf.Deserialize(decompressor);	
					} else {
						loadedObj = (T)bf.Deserialize(fs);	
					}
				} catch(Exception ex) {
					//TODO: file load error
					Console.WriteLine(ex.ToString());					
					loadedObj = new T();
				} finally {
					if(compress) decompressor.Close();
					fs.Close();
				}	
			} else {
				loadedObj = new T();
			}

			return loadedObj;
		}
		
		/// <summary>
		/// Save the given object to filename. 
		/// </summary>
		/// <param name="filename">
		/// A <see cref="System.String"/>
		/// </param>
		/// <param name="obj">
		/// A <see cref="T"/>
		/// </param>
		
		public static void SaveToFile<T>(string filename, T obj) {
			SaveToFile<T>(filename, obj, false);
		}
		
		public static void SaveToFile<T>(string filename, T obj, bool compress)	{
			//TODO: save in a different thread?
			if(MNGlobal.CreateDefaultDirectory()) {
				Console.WriteLine(@"writing to " + filename);
				
				FileStream fs = File.Open(filename, FileMode.Create, FileAccess.Write);
				GZipStream compressor = null;
				BinaryFormatter bf = new BinaryFormatter();

				try	{
					if(compress) {
						compressor = new GZipStream(fs, CompressionMode.Compress);							
						bf.Serialize(compressor, obj);
					} else {
						bf.Serialize(fs, obj);
					}
					
				} finally {
					if(compress) compressor.Close();
					fs.Close();
					Console.WriteLine(@"closed " + filename);
				}
			}
		}
		
		#endregion		
	}
}

